import asyncio
import datetime
import uuid
from app.api.deps import SessionDep
from app.crud import create_device, create_speech_data, get_device_by_mac, get_project_by_name, get_projects, get_record_by_script_hash, get_speech_data_by_speech_id, update_device
from app.websocket_manager import ManagerDep, manager
from app.models import Device, Project, Record, SpeechData, Task
from fastapi import APIRouter, WebSocket
from loguru import logger
from pydantic import BaseModel
from sqlmodel import Session

router = APIRouter(prefix="/client")


class HeartbeatResponse(BaseModel):
    devvice_id: int


@router.websocket("/ws")
async def websocket_endpoint(
    websocket: WebSocket, session: SessionDep, manager: ManagerDep
):
    await websocket.accept()
    while True:
        try:
            data = await websocket.receive_json()
        except Exception as e:
            logger.warning(e)
            break
        match data["event"]:
            case "heartbeat":
                await heartbeat(data["data"], websocket, session)
            case "scripts_dict":
                await response_scripts(data["data"])
            # {'event': 'add_task', 'data': {'create_time': 1754877353.9830658, 'device_id': 1, 'end_time': '', 'name': '本地执行', 'num': 1, 'overwrite': True, 'process': '未执行', 'result': False, 'start_time': 1754877353.9830658, 'task_hash': '8cd210bfbb0c89c8166ab5d2b156976eb9674280b46ab0464b2b7b97b9761130', 'user_id': -1}}
            case "add_task":
                await add_task(data["data"], manager, session)
            case "script_execute_log":
                await receive_script_logs(data["data"], manager)
            case "add_record":
                await add_record(data["data"], session)
            case "update_task":
                await update_task(data["data"], session)
            case "update_record":
                await update_record(data["data"], session)
            case "get_projects":
                await get_projects_api(data["data"], session,manager)
            case _:
                logger.warning(f"Received {data}")

async def get_projects_api(data: dict, session: SessionDep, manager: ManagerDep):
    device_id = data.get("device_id",-1)
    if device_id <=0:
        return
    projects = get_projects(session=session)
    projects = [{'project_id': project.id.hex, 'project_name': project.name} for project in projects]
    await manager.broadcast_to(device_id, {"event": "projects", "data": projects})

async def update_record(data: dict, session: SessionDep):
    record = get_record_by_script_hash(session=session, script_hash=data["script_hash"])
    data['log'] = data.pop("logs", "")
    if record:
        for key, value in data.items():
            if key in ["end_time","start_time"]:
                value = datetime.datetime.fromtimestamp(value) if value else None
            setattr(record, key, value)
        
        session.commit()



async def update_task(data: dict, session: SessionDep):
    logger.info(f"update_task {data}")
    task = session.get(Task, uuid.UUID(data["task_id"]))
    if task:
        for key, value in data.items():
            if key == 'task_id':
                continue
            if key == "end_time":
                value = datetime.datetime.fromtimestamp(value) if value else None
            setattr(task, key, value)
        session.commit()


async def add_record(data: dict, session: SessionDep):
    data["log"] = data.pop("logs", "")
    data["start_time"] = (
        datetime.datetime.fromtimestamp(data["start_time"])
        if data["start_time"]
        else None
    )
    data["end_time"] = (
        datetime.datetime.fromtimestamp(data["end_time"]) if data["end_time"] else None
    )

    record = Record(**data)
    session.add(record)
    session.commit()


async def receive_script_logs(data: dict, manager: ManagerDep):
    logger.info(f"receive_script_logs {data}")
    await manager.broadcast_to_web(data)


async def add_task(data: dict, manager: ManagerDep, session: SessionDep):
    logger.info(f"add_task {data}")
    task_data = {
        "create_time": datetime.datetime.fromtimestamp(data["create_time"]),
        "device_id": data["device_id"],
        "name": data["name"],
        "process": data["process"],
        "result": data["result"],
        "task_hash": data["task_hash"],
        "user_id": uuid.UUID(data["user_id"]) if data["user_id"] != -1 else None,
    }



    project_name = data.get("project_name", None)
    if project_name:
        project = get_project_by_name(session, project_name)
        if not project:
            project = Project(name=project_name)
            session.add(project)
            session.commit()
    task_data["project_id"] = project.id if project_name else None
    task = Task(**task_data)
    session.add(task)
    session.commit()
    await manager.broadcast_to(
        task.device_id, {"event": "fetch_task_id", "data": {"task_id": task.id.hex}}
    )


async def response_scripts(data: dict):
    req_id = data["reqId"]
    logger.info(f"req_id {req_id}")
    await manager.add_data(req_id, data)


async def heartbeat(data: dict, websocket: WebSocket, session: Session):
    # {'event': 'heartbeat', 'data': {'hostname': 'BICV', 'id': 4846677064854, 'ip': '192.168.46.124', 'mac': '04:68:74:76:fc:96', 'timestamp': 1754285965.7590654, 'type': 'HeartBeat'}}
    logger.info(f"heartbeat: {data}")
    device_info = {
        "hostname": data["hostname"],
        "ip": data["ip"],
        "mac": data["mac"],
        "create_time": datetime.datetime.fromtimestamp(data["timestamp"]),
        "last_online": datetime.datetime.fromtimestamp(data["timestamp"]),
    }
    device = get_device_by_mac(session, data["mac"])
    if device is None:
        device = Device(**device_info)
        create_device(session, device)
    else:
        device.last_online = datetime.datetime.fromtimestamp(data["timestamp"])
        device.ip = data["ip"]
        device.hostname = data["hostname"]
        update_device(session, device)
    if  data['uid'] != '':
        device.user_id = uuid.UUID(data['uid'])
        update_device(session, device)
    speech_data =data.get('speech_data',[])
    if len(speech_data)>0:
        for id_,task_id,language,language_name,create_time,project,user,content,desc,feedback,dept in speech_data:
            # (20, '9dfdc2c9c11d4dccbfd713d2ecb46692', 'ar-AE', '2025-09-12 03:22:00', 'F202', 'lzx', 'إدارة الملفات', '文件管理', None)
            speech_data = get_speech_data_by_speech_id(session, speech_id=task_id)
            if speech_data is None:
                speech_data = SpeechData(
                    task_id=task_id,
                    language=language,
                    language_name=language_name,
                    create_time=create_time,
                    project=project,
                    user=user,
                    content=content,
                    desc=desc,
                    feedback=feedback,
                    dept=dept
                )
            else:
                speech_data.feedback = feedback
            logger.info(speech_data)
            create_speech_data(session, speech_data)

    manager.add(websocket, device.id)
    await websocket.send_json({"event": "heartbeat", "data": {"device_id": device.id}})
